package com.auth.filter;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.auth.common.result.Result;
import com.auth.common.result.ResultCodeEnum;
import com.auth.custom.CustomUser;
import com.auth.utils.ResponseUtils;
import com.auth.utils.StringPool;
import com.auth.vo.system.LoginVo;
import jwt.JwtHelperUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author:Tangjiachang
 * @Date 2023/7/16
 * @Description:
 */
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

    private final RedisTemplate redisTemplate;
    public TokenLoginFilter(AuthenticationManager manager, RedisTemplate redisTemplate) {
        this.setAuthenticationManager(manager);
        this.setPostOnly(false);
        this.redisTemplate = redisTemplate;
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(StringPool.LOGIN_URL, StringPool.POST));
    }

    /**
     * @Author Tangjiachang
     * @Description 认证
     * @Date 15:57 2023/7/20
     * @Param [request, response]
     * @return org.springframework.security.core.Authentication
     **/
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response) throws AuthenticationException {
        try {
            LoginVo loginVo = new ObjectMapper().readValue(request.getInputStream(), LoginVo.class);
            Authentication authen = new UsernamePasswordAuthenticationToken(loginVo.getUsername(), loginVo.getPassword());
            return this.getAuthenticationManager().authenticate(authen);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Author Tangjiachang
     * @Description 认证成功调用
     * @Date 15:57 2023/7/20
     * @Param
     * @return
     **/
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        // 获取当前用户
        CustomUser customUser = (CustomUser) authResult.getPrincipal();
        String token = JwtHelperUtils.createToken(customUser.getSysUser().getId(), customUser.getSysUser().getUsername());
        Map<String, Object> map = new HashMap<String, Object>(0) {{
            put(StringPool.TOKEN, token);
        }};
        // 获取当前用户权限数据，存储到redis中
        redisTemplate.opsForValue().set(customUser.getUsername(),
                JSON.toJSONString(customUser.getAuthorities()));
        ResponseUtils.out(response, request, Result.ok(map));
    }

    /**
     * @Author Tangjiachang
     * @Description 认证失败调用
     * @Date 15:57 2023/7/20
     * @Param [request, response, failed]
     * @return void
     **/
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        ResponseUtils.out(response, request, Result.build(null, ResultCodeEnum.LOGIN_FAIL));
    }
}
